define(function (require, exports, module) {    
    var TreeNode = React.createClass({
        getInitialState: function() {           
            var node = this.props.node;
            return {
                expanded: node.state && node.state.hasOwnProperty('expanded') ?
                    node.state.expanded : false,
                selected: node.state && node.state.hasOwnProperty('selected') ?
                    node.state.selected : false,
                singleSelect: this.props.option.hasOwnProperty("singleSelect") ? 
                    this.props.option.singleSelect : true
            };
        },
        toggleExpanded: function(event) {
            this.setState({ expanded: !this.state.expanded });       
        },
        toggleSelected: function(event) {        
            var selected = !this.state.selected;         
            if (this.state.singleSelect) {
                var oldSelectedItem = this.props.tree.oldSelectedItem;                
                if (selected) {
                    if (oldSelectedItem && oldSelectedItem !== this) {
                        oldSelectedItem.toggleSelected();
                    }
                    this.props.tree.oldSelectedItem = this;
                } else {
                    if (oldSelectedItem && oldSelectedItem === this) {
                        this.props.tree.oldSelectedItem = null;
                    }
                }
            }

            if (selected){
                this.props.tree.addSelectedNode(this.props.node);
            }
            else{
                this.props.tree.removeSelectedNode(this.props.node);
            }          
            this.setState({
                selected: selected
            });
        },
        componentWillReceiveProps: function(nextProps) {
            this.state.selected = false;            
        },
        componentDidMount: function(){    
            var _this = this;
            $(ReactDOM.findDOMNode(this)).on('click', '.tree-actions>li', function(event){           
                $(ReactDOM.findDOMNOde(_this.props.tree)).trigger("action."+$(this).attr("name"), _this.props.node);
                event.stopPropagation();
            });
        },
        handleClick : function(event) {
            this.toggleExpanded(this.props.node.id, event);
            if (this.props.option.enableSelect) {
                this.toggleSelected(this.props.node.id, event);
            }
            $(ReactDOM.findDOMNode(this.props.tree)).trigger("clickNode", this.props.node);
        },
        render: function () {        
            var node = this.props.node;
            var children = [];
            if (node.children) {
                var _this = this;
                _.each(node.children, function(node, i) {
                    children.push(<TreeNode node={node} option = {_this.props.option} tree = {_this.props.tree} children={_this.props.children} level={_this.props.level+1} key={i}/>); }); }
        
            var icon;       
            if (node.children) {
                if (!this.state.selected) {
                    if (!this.state.expanded) {
                        icon = "fa fa-folder";
                    } else {
                        icon = "fa fa-folder-open";
                    }
                }
                else{
                    icon = "fa fa-check";
                }
            }
            else {        
                if (!this.state.selected){
                    if (this.props.option.style == 'tree-solid-line'){
                        icon = "fa fa-folder";
                    }
                    else{
                        icon = "fa tree-dot";    
                    }                
                }   
                else {               
                    icon = "fa fa-check"; 
                }           
            }
         
             var classes = {
                'tree-selected' : this.state.selected,         
            }
          
            if (node.children){
                return (
                    <div className={classNames(classes,'tree-folder')} id ={node.id}>
                        <div ref='header' onClick={this.handleClick} className = {"tree-folder-header"}>
                            <i className={icon}></i>
                            <div className="tree-folder-name">{node.name}<div className="tree-actions">{this.props.children}</div></div>
                        </div>
                        <div className="tree-folder-content" style={{display : !this.state.expanded ? 'none': ''}}>{children}</div>       
                        <div className="tree-loader" style={{display: "none"}}><img src="/img/input-spinner.gif"></img></div>
                    </div>
                );
            }
            else{
                return (
                    <div ref="item" id ={node.id} onClick={this.handleClick} className={classNames(classes,'tree-item')}>                   
                        <i className={icon}></i>
                        <div className="tree-item-name">{node.name}</div><div className="tree-actions">{this.props.children}</div>   
                    </div>
                );
            }
        }
    });
   
    var FolderTree = React.createClass({       
        getInitialState: function () {
            return {
               selectedNode : {},
               oldSelectedItem : null  
            };
        },
        componentDidMount: function(){                          
            $(ReactDOM.findDOMNode(this)).data("getSelectedNode", function(){              
                return _.values(this.state.selectedNode);                    
            }.bind(this))

            $(this.props.data).on("change", function(){
               this.forceUpdate();
            }.bind(this));
        },
        componentWillReceiveProps : function(nextProps) {
            this.state.selectedNode = {};        
            this.state.oldSelectedItem = null;  
        },
        addSelectedNode: function(node){            
            this.state.selectedNode[node.id] = node;
        },
        removeSelectedNode: function(node){
            delete this.state.selectedNode[node.id];
        },
        render: function () {       
            var childrenNode = this.props.data.children;
            var option = this.props.option;
            var childern = [];
            if (childrenNode) {
                var _this = this;
                _.each(childrenNode, function (node, i) {
                    childern.push(<TreeNode node={node} level={1} option={option} visible={true} children={_this.props.children} tree = {_this} key={i}></TreeNode>) });
            }
            var className = "tree " + this.props.option.style;
            return (
                <div id={this.props.option.id} style={{"height": "100%"}} className={className}>
                    {childern}
                </div>
            )
        }
        
    });
    return FolderTree
});